/**
 * This file is part of Virtual Environment Tutoring Engine (VETE).
 * Copyright (C) 2011 Iowa State University.
 *
 * VETE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **/
 
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Stack;

public class Engine {

	private static int soldierCount = 0;
	private static int insurgentCount = 0;
	private static int civilianCount = 0;
	private static int bombCount = 0;
	private static boolean skip = false;
	
	private static ArrayList<State> states = new ArrayList<State>();
	private static ArrayList<State> atomicStates = new ArrayList<State>();
	private static ArrayList<State> complexStates = new ArrayList<State>();
	private static Stack<State> History = new Stack<State>();

	private static State getCurrentAtomicState() throws FileNotFoundException {
		// Retrieve all properties of all entities
		Scanner in = new Scanner((Readable) new FileReader("C:/VBS2/Current_State.txt"));
		ArrayList<String> values = new ArrayList<String>();
		String buff;
		while( in.hasNext() ) {
			buff = in.nextLine();
			values.add(buff);
		}			
		in.close();
		int valuesCounter = 0;
		
		ArrayList<Soldier> soldierList = new ArrayList<Soldier>();
		ArrayList<Bomb> bombList = new ArrayList<Bomb>();
		ArrayList<Civilian> civilianList = new ArrayList<Civilian>();
		ArrayList<Insurgent> insurgentList = new ArrayList<Insurgent>();
		
		String entityID, health, action, diffused, exploded;
		
		skip = false;
		if(values.size()!=24) { // File is only partially read
			// System.out.println(values.size());
			skip = true;
			return null;
		}
		
		// Soldier
		for(int j=0; j<soldierCount; j++) {
			String [] loc = new String[3];
			entityID = values.get(valuesCounter++);
			health = values.get(valuesCounter++);			
			loc[0] = values.get(valuesCounter++); loc[1] = values.get(valuesCounter++); loc[2] = values.get(valuesCounter++);
			action = values.get(valuesCounter++);
			Soldier soldier = new Soldier(entityID, loc, null, health, action);
			soldierList.add(soldier);
		}
		// Insurgent
		for(int j=0; j<insurgentCount; j++) {
			String [] loc = new String[3];
			entityID = values.get(valuesCounter++);
			health = values.get(valuesCounter++);			
			loc[0] = values.get(valuesCounter++); loc[1] = values.get(valuesCounter++); loc[2] = values.get(valuesCounter++);
			action = values.get(valuesCounter++);		
			Insurgent insurgent = new Insurgent(entityID, loc, null, health, action);
			insurgentList.add(insurgent);
		}
		// Civilian
		for(int j=0; j<civilianCount; j++) {
			String [] loc = new String[3];
			entityID = values.get(valuesCounter++);
			health = values.get(valuesCounter++);			
			loc[0] = values.get(valuesCounter++); loc[1] = values.get(valuesCounter++); loc[2] = values.get(valuesCounter++);
			action = values.get(valuesCounter++);
			Civilian civilian = new Civilian(entityID, loc, null, health, action);
			civilianList.add(civilian);
		}
		// Bomb
		for(int j=0; j<bombCount; j++) {
			String [] loc = new String[3];
			entityID = values.get(valuesCounter++);	
			loc[0] = values.get(valuesCounter++); loc[1] = values.get(valuesCounter++); loc[2] = values.get(valuesCounter++);
			diffused = values.get(valuesCounter++);
			exploded = values.get(valuesCounter++);
			Bomb bomb = new Bomb(entityID, loc, diffused, exploded);
			bombList.add(bomb);
		}
		
		EntitySet entitySet = new EntitySet(soldierList, insurgentList, civilianList, bombList);			
		State currentAtomic = new State(null, -1, 0, 0, null, null, null, entitySet);
		//currentAtomic.printDetails();
		// Find a match with the user defined atomic states
		int highestPriorityIndex = 0;
		int highestPriority = -1;// states.get(highestPriorityIndex).getPriority();
		for(int i=0; i<atomicStates.size(); i++) {
			if(currentAtomic.stateCompare(states.get(i))) { // Without priorities, the state returned is the first match from the states defined by the author
				//System.out.println(atomicStates.get(i).getName());
				//atomicStates.get(i).printDetails();
				if(states.get(i).getPriority() > highestPriority ) {
					highestPriorityIndex = i;
					highestPriority = states.get(i).getPriority();
				}
			}
		}
		return atomicStates.get(highestPriorityIndex);
		
		//return null;
	}

	private static State getCurrentComplexState()
	{
		State currentComplex = null;
		// Find a match with largest possible complex state
		// Use the stack (History)
		// Need to find largest possible RegEx match that ends with stack top

		return currentComplex;
	}

	private static void display(String prompt) 
	{	
		System.out.println(prompt);
	}
	
	static void buildStates() throws FileNotFoundException {
		//Scanner in = new Scanner(System.in);
		Scanner in = new Scanner((Readable) new FileReader("C:/VBS2/AuthorStates.txt"));
		ArrayList<String> values = new ArrayList<String>();
		String buff;
		while( in.hasNext() ) {
			buff = in.nextLine();
			values.add(buff);
		}
		
		in.close();
		int valuesCounter = 0;
		
		for(int i = 0; i<4; i++) { // Number of user defined states in AuthorStates.txt
			ArrayList<String> hintList = new ArrayList<String>(), JITList = new ArrayList<String>(), promptList = new ArrayList<String>();
			ArrayList<Soldier> soldierList = new ArrayList<Soldier>();
			ArrayList<Bomb> bombList = new ArrayList<Bomb>();
			ArrayList<Civilian> civilianList = new ArrayList<Civilian>();
			ArrayList<Insurgent> insurgentList = new ArrayList<Insurgent>();
			
			String hint, JIT, prompt;
			int type, kind, priority;
			String name;
			//System.out.println(values.size());
			name = values.get(valuesCounter++);
			priority = Integer.parseInt(values.get(valuesCounter++).trim());
			type = Integer.parseInt(values.get(valuesCounter++).trim());
			kind = Integer.parseInt(values.get(valuesCounter++).trim());			
			hint = values.get(valuesCounter++);
			JIT = values.get(valuesCounter++);
			prompt = values.get(valuesCounter++);		
			
			hintList.add(hint);
			JITList.add(JIT);
			promptList.add(prompt);			
			
			String entityID, health, action, diffused, exploded;
			
			// Soldier
			for(int j=0; j<soldierCount; j++) {
				String [] loc = new String[3];
				entityID = values.get(valuesCounter++);
				health = values.get(valuesCounter++);			
				loc[0] = values.get(valuesCounter++); loc[1] = values.get(valuesCounter++); loc[2] = values.get(valuesCounter++);
				action = values.get(valuesCounter++);
				Soldier soldier = new Soldier(entityID, loc, null, health, action);
				soldierList.add(soldier);
			}

			// Insurgent
			for(int j=0; j<insurgentCount; j++) {
				String [] loc = new String[3];
				entityID = values.get(valuesCounter++);
				health = values.get(valuesCounter++);			
				loc[0] = values.get(valuesCounter++); loc[1] = values.get(valuesCounter++); loc[2] = values.get(valuesCounter++);
				action = values.get(valuesCounter++);		
				Insurgent insurgent = new Insurgent(entityID, loc, null, health, action);
				insurgentList.add(insurgent);
			}
			// Civilian
			for(int j=0; j<civilianCount; j++) {
				String [] loc = new String[3];
				entityID = values.get(valuesCounter++);
				health = values.get(valuesCounter++);			
				loc[0] = values.get(valuesCounter++); loc[1] = values.get(valuesCounter++); loc[2] = values.get(valuesCounter++);
				action = values.get(valuesCounter++);
				Civilian civilian = new Civilian(entityID, loc, null, health, action);
				civilianList.add(civilian);
			}
			// Bomb
			for(int j=0; j<bombCount; j++) {
				String [] loc = new String[3];
				entityID = values.get(valuesCounter++);	
				loc[0] = values.get(valuesCounter++); loc[1] = values.get(valuesCounter++); loc[2] = values.get(valuesCounter++);
				diffused = values.get(valuesCounter++);
				exploded = values.get(valuesCounter++);
				Bomb bomb = new Bomb(entityID, loc, diffused, exploded);
				bombList.add(bomb);
			}
			
			EntitySet entitySet = new EntitySet(soldierList, insurgentList, civilianList, bombList);			
			State S = new State(name, priority,  kind,type, hintList, JITList, promptList, entitySet);
			states.add(S);
			if(type==0)
				atomicStates.add(S);
			else
				complexStates.add(S);	
			
			valuesCounter++;
		}		
	}
	
	public static void main(String args[]) throws FileNotFoundException {
		soldierCount = 1;
		insurgentCount = 1;
		civilianCount = 1;
		bombCount = 1;
		
		buildStates();
		
		while(true) {
		//for(int i=0; i<1; i++) { 
			State currentAtomic = getCurrentAtomicState();
			if(skip) {System.out.println("Skipped."); continue;}
			System.out.println("Current Atomic State:" + currentAtomic.getName());
			if( History.size()!=0) System.out.println("Peek:" + History.peek().getName());
			if( History.size()==0 || !History.peek().getName().equals(currentAtomic.getName())) {
				History.add(currentAtomic);
				//State currentComplex = getCurrentComplexState
				//State current = (currentComplex != null)? currentComplex:currentAtomic;
				//if (current.getType() == 2) { break; } // Failed state
				//if (current.getType() == 3) { break; } // Goal state
			}
			//display(currentAtomic.getPrompt(0));
			displayHistory();
			//currentAtomic.printDetails();
			// Process and display appropriate JITs
			// Display hints if user asks for them
		}
	}
	
	private static void displayHistory() {
		System.out.println("History:");
		for(int i=0; i<History.size(); i++) {
			System.out.println(History.get(i).getName());
		}
		System.out.println();
	}
}
